﻿using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Http.Json;
using System.Net;
using System.Text.Json;
using CollabApp.API;

namespace CollabApp.Tests;

/// <summary>
/// 集成测试类 - 测试整个API的端到端功能
/// </summary>
public class AuthIntegrationTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;
    private readonly HttpClient _client;

    public AuthIntegrationTests(WebApplicationFactory<Program> factory)
    {
        _factory = factory;
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task Register_ValidInput_ShouldReturnSuccess()
    {
        // Arrange
        var registerRequest = new
        {
            Username = $"testuser_{Guid.NewGuid():N}",
            Password = "password123",
            ConfirmPassword = "password123",
            Avatar = "https://example.com/avatar.jpg"
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/auth/register", registerRequest);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        
        var content = await response.Content.ReadAsStringAsync();
        var result = JsonSerializer.Deserialize<JsonElement>(content);
        
        result.GetProperty("code").GetInt32().Should().Be(1000);
        result.GetProperty("message").GetString().Should().Be("注册成功，请前往登录界面登录！");
    }

    [Fact]
    public async Task Register_DuplicateUsername_ShouldReturnError()
    {
        // Arrange
        var username = $"duplicateuser_{Guid.NewGuid():N}";
        var registerRequest = new
        {
            Username = username,
            Password = "password123",
            ConfirmPassword = "password123",
            Avatar = "https://example.com/avatar.jpg"
        };

        // Act - 第一次注册
        await _client.PostAsJsonAsync("/api/auth/register", registerRequest);
        
        // Act - 第二次注册相同用户名
        var response = await _client.PostAsJsonAsync("/api/auth/register", registerRequest);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        
        var content = await response.Content.ReadAsStringAsync();
        var result = JsonSerializer.Deserialize<JsonElement>(content);
        
        result.GetProperty("code").GetInt32().Should().Be(1001);
        result.GetProperty("message").GetString().Should().Be("用户名已存在，请重新输入！！！");
    }

    [Fact]
    public async Task Login_ValidCredentials_ShouldReturnTokens()
    {
        // Arrange - 先注册一个用户
        var username = $"loginuser_{Guid.NewGuid():N}";
        var password = "password123";
        var registerRequest = new
        {
            Username = username,
            Password = password,
            ConfirmPassword = password,
            Avatar = "https://example.com/avatar.jpg"
        };

        await _client.PostAsJsonAsync("/api/auth/register", registerRequest);

        var loginRequest = new
        {
            Username = username,
            Password = password,
            RememberMe = false
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/auth/login", loginRequest);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        
        var content = await response.Content.ReadAsStringAsync();
        var result = JsonSerializer.Deserialize<JsonElement>(content);
        
        result.GetProperty("code").GetInt32().Should().Be(1000);
        result.GetProperty("message").GetString().Should().Be("登录成功！");
        
        var data = result.GetProperty("data");
        data.GetProperty("token").GetString().Should().NotBeNullOrEmpty();
        data.GetProperty("refreshToken").GetString().Should().NotBeNullOrEmpty();
        
        var user = data.GetProperty("user");
        user.GetProperty("username").GetString().Should().Be(username);
        user.GetProperty("nickname").GetString().Should().Be(username);
    }

    [Fact]
    public async Task Login_InvalidCredentials_ShouldReturnError()
    {
        // Arrange
        var loginRequest = new
        {
            Username = "nonexistentuser",
            Password = "wrongpassword",
            RememberMe = false
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/auth/login", loginRequest);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        
        var content = await response.Content.ReadAsStringAsync();
        var result = JsonSerializer.Deserialize<JsonElement>(content);
        
        result.GetProperty("code").GetInt32().Should().Be(1001);
        result.GetProperty("message").GetString().Should().Be("用户不存在，请重新输入！！！");
    }

    [Theory]
    [InlineData("ab", "password123", "password123", 1003, "用户名长度需为3-20个字符！")]
    [InlineData("verylongusernamethatexceedslimit", "password123", "password123", 1003, "用户名长度需为3-20个字符！")]
    [InlineData("validuser", "12345", "12345", 1004, "密码长度需为6-20个字符！")]
    [InlineData("validuser", "password123", "differentpassword", 1002, "两次输入的密码不一致，请重新输入！")]
    public async Task Register_InvalidInput_ShouldReturnExpectedError(
        string username, string password, string confirmPassword, int expectedCode, string expectedMessage)
    {
        // Arrange
        var registerRequest = new
        {
            Username = username,
            Password = password,
            ConfirmPassword = confirmPassword,
            Avatar = "https://example.com/avatar.jpg"
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/auth/register", registerRequest);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        
        var content = await response.Content.ReadAsStringAsync();
        var result = JsonSerializer.Deserialize<JsonElement>(content);
        
        result.GetProperty("code").GetInt32().Should().Be(expectedCode);
        result.GetProperty("message").GetString().Should().Be(expectedMessage);
    }

    [Fact]
    public async Task RefreshToken_ValidToken_ShouldReturnNewTokens()
    {
        // Arrange - 先注册并登录获取tokens
        var username = $"refreshuser_{Guid.NewGuid():N}";
        var password = "password123";
        var registerRequest = new
        {
            Username = username,
            Password = password,
            ConfirmPassword = password,
            Avatar = "https://example.com/avatar.jpg"
        };

        await _client.PostAsJsonAsync("/api/auth/register", registerRequest);

        var loginRequest = new
        {
            Username = username,
            Password = password,
            RememberMe = false
        };

        var loginResponse = await _client.PostAsJsonAsync("/api/auth/login", loginRequest);
        var loginContent = await loginResponse.Content.ReadAsStringAsync();
        var loginResult = JsonSerializer.Deserialize<JsonElement>(loginContent);
        var refreshToken = loginResult.GetProperty("data").GetProperty("refreshToken").GetString();

        var refreshRequest = new
        {
            RefreshToken = refreshToken
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/auth/refresh", refreshRequest);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        
        var content = await response.Content.ReadAsStringAsync();
        var result = JsonSerializer.Deserialize<JsonElement>(content);
        
        result.GetProperty("code").GetInt32().Should().Be(1000);
        result.GetProperty("message").GetString().Should().Be("令牌刷新成功！");
        
        var data = result.GetProperty("data");
        data.GetProperty("token").GetString().Should().NotBeNullOrEmpty();
        data.GetProperty("refreshToken").GetString().Should().NotBeNullOrEmpty();
    }

    [Fact]
    public async Task RefreshToken_InvalidToken_ShouldReturnError()
    {
        // Arrange
        var refreshRequest = new
        {
            RefreshToken = "invalid_refresh_token"
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/auth/refresh", refreshRequest);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        
        var content = await response.Content.ReadAsStringAsync();
        var result = JsonSerializer.Deserialize<JsonElement>(content);
        
        result.GetProperty("code").GetInt32().Should().Be(1001);
        result.GetProperty("message").GetString().Should().Be("无效的刷新令牌！");
    }
}

/// <summary>
/// 基础实体测试类 - 测试BaseEntity的共有功能
/// </summary>
public class BaseEntityTests
{
    [Fact]
    public void BaseEntity_NewInstance_ShouldHaveDefaultValues()
    {
        // Arrange & Act
        var entity = new TestEntity();

        // Assert
        entity.Id.Should().NotBeEmpty();
        entity.CreatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(5));
        entity.UpdatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(5));
        entity.IsDeleted.Should().BeFalse();
    }

    [Fact]
    public void BaseEntity_TwoInstances_ShouldHaveDifferentIds()
    {
        // Arrange & Act
        var entity1 = new TestEntity();
        var entity2 = new TestEntity();

        // Assert
        entity1.Id.Should().NotBe(entity2.Id);
    }

    /// <summary>
    /// 用于测试的实体类
    /// </summary>
    private class TestEntity : CollabApp.Domain.Entities.BaseEntity
    {
    }
}
